# 使用MNIST数据集进行验证，以确认Dropout的效果
# Dropout原理：
#     如果网络模型变得很复杂后，只有权值衰减就难以应对了。这就为Dropout使用
# 提供了舞台。
#     Dropout是一种在学习的过程中随机删除神经元的方法。训练时，随机选出隐藏层
# 神经元，然后将其删除。被删除的神经元不再进行信号的传递。每次传递一次数据，就会
# 随机选择要删除的神经元。然后，测试时，虽然会传递所有的神经元信号，但是对于每个
# 神经元的输出，要乘以训练时的删除比例后再输出。

import sys,os
sys.path.append(os.pardir)
import numpy as np
import matplotlib.pyplot as plt 
from dataset.mnist import load_mnist
from common.multi_layer_net_extend import MultiLayerNetExtend
from common.trainer import Trainer

# 载入MNIST数据
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)

# 创造过拟合条件：
#     1. 减少训练数据
x_train = x_train[:300]
t_train = t_train[:300]

# 设定是否使用Dropout，以及比例
use_dropout = False # 不使用Dropout的情况下为False
dropout_ratio = 0.2

# 初始化网络，创造过拟合条件：
    # 2. 增加网络层数
network = MultiLayerNetExtend(input_size=784,hidden_size_list=[100,100,100,100,100,100], # 构建一个7层网络，创造过拟合的条件
                              output_size=10,use_dropout=use_dropout,dropout_ration=dropout_ratio)

# 训练
trainer = Trainer(network,x_train,t_train,x_test,t_test,
                  epochs=301,mini_batch_size=100,
                  optimizer='sgd',optimizer_param={'lr':0.01},
                  verbose=True)
trainer.train()

train_acc_list,test_acc_list = trainer.train_acc_list,trainer.test_acc_list

# 绘制图形==========
markers = {'train':'o','test':'s'}
x = np.arange(len(train_acc_list))
plt.plot(x,train_acc_list,marker='o',label='train',markevery=10)
plt.plot(x,test_acc_list,marker='s',label='test',markevery=10)
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.ylim(0,1.0)
if use_dropout:
    plt.title("With dropout")
else:
    plt.title('Without dropout')
plt.legend(loc='lower right')
plt.show()
